package auth

import (
	"goskeleton/app/global/variable"
	"goskeleton/app/model"
	"goskeleton/app/utils/data_bind"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func CreateAuthOrganizationFactory(sqlType string) *AuthOrganizationPostModel {
	return &AuthOrganizationPostModel{BaseModel: model.BaseModel{DB: model.UseDbConn(sqlType)}}
}

type AuthOrganizationPostModel struct {
	model.BaseModel
	Fid       int    `json:"fid"`
	Title     string `json:"title"`
	NodeType  int    `json:"node_type" gorm:"column:node_type;type:tinyint(1);default:1;comment:节点类型：1=部门，2=角色/岗位"` // 1=部门，2=角色/岗位
	Status    int    `json:"status"`
	PathInfo  string `json:"path_info"`
	NodeLevel int    `json:"node_level" gorm:"column:node_level;type:int;default:0;comment:节点深度级别"`
	Remark    string `json:"remark"`
	RoleLevel int    `json:"role_level" gorm:"column:role_level;type:int;default:0;comment:角色等级"`
}

// 表名
func (a *AuthOrganizationPostModel) TableName() string {
	return "tb_auth_organization_post"
}

func (a *AuthOrganizationPostModel) GetCount(fid int, title string) (count int64) {
	a.Model(a).Select("id").Where("fid = ? AND title like ?", fid, "%"+title+"%").Count(&count)
	return
}
func (a *AuthOrganizationPostModel) List(limitStart int, limit int, fid int, title string) (data []AuthOrganizationPostModel) {
	a.Model(a).Select("id", "fid", "title", "node_type", "status", "path_info", "node_level", "remark", "created_at", "updated_at").Where("fid = ? AND title like ?", fid, "%"+title+"%").Offset(limitStart).Limit(limit).Find(&data)
	return
}

func (a *AuthOrganizationPostModel) InsertData(c *gin.Context) bool {
	var tmp AuthOrganizationPostModel
	if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
		var counts int64
		if res := a.Model(a).Where("fid=? and title=?", tmp.Fid, tmp.Title).Count(&counts); res.Error == nil && counts > 0 {
			return false
		} else {
			if res := a.Create(&tmp); res.Error == nil {
				// 插入新数据时，如果提供了NodeLevel值则使用，否则自动计算
				var nodeLevel *int
				if tmp.NodeLevel > 0 {
					nodeLevel = &tmp.NodeLevel
				}
				_ = a.updatePathInfoNodeLevel(int(tmp.Id), nodeLevel)
				return true
			} else {
				variable.ZapLog.Error("AuthOrganizationPostModel 数据新增出错：", zap.Error(res.Error))
			}
		}
	} else {
		variable.ZapLog.Error("AuthOrganizationPostModel 数据从验证器绑定到model出错：", zap.Error(err))
	}
	return false
}

// 更新path_info 、node_level 字段
func (a *AuthOrganizationPostModel) updatePathInfoNodeLevel(curItemid int, nodeLevel *int) bool {
	// 如果提供了nodeLevel值，则使用该值，否则自动计算
	var sql string
	var res *gorm.DB

	if nodeLevel != nil {
		// 使用提供的nodeLevel值
		sql = `
			UPDATE tb_auth_organization_post a  LEFT JOIN tb_auth_organization_post  b
			ON  a.fid=b.id
			SET  a.node_level=?,  a.path_info=CONCAT(IFNULL(b.path_info, '0'),',',a.id)
			WHERE  a.id=?
		`
		res = a.Exec(sql, *nodeLevel, curItemid)
	} else {
		// 自动计算nodeLevel值
		sql = `
			UPDATE tb_auth_organization_post a  LEFT JOIN tb_auth_organization_post  b
			ON  a.fid=b.id
			SET  a.node_level=IFNULL(b.node_level, 0)+1,  a.path_info=CONCAT(IFNULL(b.path_info, '0'),',',a.id)
			WHERE  a.id=?
		`
		res = a.Exec(sql, curItemid)
	}

	if res.Error == nil && res.RowsAffected >= 0 {
		return true
	} else {
		variable.ZapLog.Error("tb_auth_organization_post 更新 path_info 失败", zap.Error(res.Error))
	}
	return false
}

func (a *AuthOrganizationPostModel) GetByFid(fid int) (data []AuthOrganizationPostTree, err error) {
	sql := `
		SELECT  
		id,fid,title,node_type,status,path_info,node_level,remark ,
		(SELECT  CASE  WHEN  COUNT(*) =0 THEN 1 ELSE  0 END  FROM tb_auth_organization_post  WHERE  fid=a.id ) AS  is_leaf
		FROM   tb_auth_organization_post  a  WHERE  fid=?
	`
	err = a.Raw(sql, fid).Scan(&data).Error
	return
}

// 根据ID查询单挑数据
func (a *AuthOrganizationPostModel) GetById(id int, data *AuthOrganizationPostModel) (err error) {
	err = a.Model(a).Where("id = ?", id).Find(data).Error
	return
}

func (a *AuthOrganizationPostModel) UpdateData(c *gin.Context) bool {
	var tmp AuthOrganizationPostModel

	if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
		// Omit 表示忽略指定字段(CreatedAt, NodeType)，其他字段全量更新
		// NodeType字段不应该在编辑时被修改，它由系统根据数据类型自动设置
		if res := a.Omit("CreatedAt", "NodeType").Save(&tmp); res.Error == nil {
			// 如果提供了NodeLevel值，则传递该值，否则传递nil让系统自动计算
			var nodeLevel *int
			if tmp.NodeLevel > 0 {
				nodeLevel = &tmp.NodeLevel
			}
			_ = a.updatePathInfoNodeLevel(int(tmp.Id), nodeLevel)
		}
		return true
	} else {
		variable.ZapLog.Error("AuthOrganizationPostModel 数据更新失败，错误详情：", zap.Error(err))
	}
	return false

}

func (a *AuthOrganizationPostModel) DeleteData(id int) bool {
	if res := a.Delete(a, id); res.Error == nil {
		return true
	} else {
		variable.ZapLog.Error("AuthOrganizationPostModel 删除数据出错：", zap.Error(res.Error))
	}
	return false
}
func (a *AuthOrganizationPostModel) HasSubList(id int) (count int64) {
	a.Model(a).Select("id").Where("fid=?", id).Count(&count)
	return
}

func (a *AuthOrganizationPostModel) GetByIds(ids []int) (AuthOrganizationPostModel []AuthOrganizationPostModel) {
	a.Where("id IN ?", ids).Find(&AuthOrganizationPostModel)
	return
}

func (a *AuthOrganizationPostModel) GetByIdsScan(ids []int) (AllAuth []AllAuth) {
	a.Model(a).Select("id", "title", "fid").Where("id IN ?", ids).Scan(&AllAuth)
	return
}

func (a *AuthOrganizationPostModel) GetAll(fid int) (AllAuth []*AllAuth) {
	a.Model(a).Select("id", "title", "fid").Where("fid=?", fid).Scan(&AllAuth)
	return
}

// GetRolesOnlyWithPagination 获取仅角色/岗位类型的数据（node_type=2）并分页
func (a *AuthOrganizationPostModel) GetRolesOnlyWithPagination(limitStart int, limit int, title string) (data []AuthOrganizationPostModel, count int64) {
	// 构建查询条件
	query := a.Model(a).Where("node_type = ?", 2) // 2表示角色/岗位
	if title != "" {
		query = query.Where("title LIKE ?", "%"+title+"%")
	}

	// 获取总数
	query.Count(&count)

	// 获取分页数据
	query.Select("id", "fid", "title", "node_type", "status", "path_info", "node_level", "remark", "created_at", "updated_at").
		Offset(limitStart).Limit(limit).Find(&data)

	return
}

// GetRolesWithParentTitle 获取仅角色/岗位类型的数据（node_type=2）并分页，包含父级title
func (a *AuthOrganizationPostModel) GetRolesWithParentTitle(limitStart int, limit int, title string) (data []RoleWithParentTitle, count int64) {
	// 构建SQL查询，通过LEFT JOIN获取父级title
	sql := `
		SELECT 
			a.id, a.fid, a.title, b.title as parent_title, a.node_type, a.status, 
			a.path_info, a.node_level, a.remark, a.created_at, a.updated_at
		FROM tb_auth_organization_post a
		LEFT JOIN tb_auth_organization_post b ON a.fid = b.id
		WHERE a.node_type = ?
	`

	var args []interface{}
	args = append(args, 2) // 2表示角色/岗位

	if title != "" {
		sql += " AND a.title LIKE ?"
		args = append(args, "%"+title+"%")
	}

	// 获取总数
	countSql := "SELECT COUNT(*) FROM tb_auth_organization_post a WHERE a.node_type = ?"
	if title != "" {
		countSql += " AND a.title LIKE ?"
		argsCount := []interface{}{2}
		if title != "" {
			argsCount = append(argsCount, "%"+title+"%")
		}
		a.Raw(countSql, argsCount...).Scan(&count)
	} else {
		a.Raw(countSql, 2).Scan(&count)
	}

	// 添加分页
	sql += " ORDER BY a.id DESC LIMIT ? OFFSET ?"
	args = append(args, limit, limitStart)

	// 执行查询
	a.Raw(sql, args...).Scan(&data)
	variable.ZapLog.Warn("AuthOrganizationPostModel GetRolesWithParentTitle 数据查询出错", zap.Any("res", data))
	return
}

// GetRolesWithParentTitleByFid 根据fid获取角色/岗位类型的数据（node_type=2）并分页，包含父级title
func (a *AuthOrganizationPostModel) GetRolesWithParentTitleByFid(fid int, limitStart int, limit int, title string) (data []RoleWithParentTitle, count int64) {
	// 构建SQL查询，通过LEFT JOIN获取父级title
	sql := `
		SELECT 
			a.id, a.fid, a.title, b.title as parent_title, a.node_type, a.status, 
			a.path_info, a.node_level, a.remark, a.created_at, a.updated_at
		FROM tb_auth_organization_post a
		LEFT JOIN tb_auth_organization_post b ON a.fid = b.id
		WHERE a.node_type = ? AND a.fid = ?
	`

	var args []interface{}
	args = append(args, 2) // 2表示角色/岗位
	args = append(args, fid)

	if title != "" {
		sql += " AND a.title LIKE ?"
		args = append(args, "%"+title+"%")
	}

	// 获取总数
	countSql := "SELECT COUNT(*) FROM tb_auth_organization_post a WHERE a.node_type = ? AND a.fid = ?"
	if title != "" {
		countSql += " AND a.title LIKE ?"
		argsCount := []interface{}{2, fid}
		if title != "" {
			argsCount = append(argsCount, "%"+title+"%")
		}
		a.Raw(countSql, argsCount...).Scan(&count)
	} else {
		a.Raw(countSql, 2, fid).Scan(&count)
	}

	// 添加分页
	sql += " ORDER BY a.id DESC LIMIT ? OFFSET ?"
	args = append(args, limit, limitStart)

	// 执行查询
	a.Raw(sql, args...).Scan(&data)

	return
}

// GetAllAsTree 查询所有部门数据并以树状结构返回
// @Description 递归构建部门组织架构的完整树状结构
// @Param rootFid int 根节点的父ID，通常为0表示从顶级开始
// @Return []AuthOrganizationPostTree 树状结构数据
func (a *AuthOrganizationPostModel) GetAllAsTree(rootFid int) ([]AuthOrganizationPostTree, error) {
	// 查询所有部门数据
	var allData []AuthOrganizationPostTree
	sql := `
		SELECT  
			id, fid, title, node_type, status, path_info, node_level, remark,
			(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
			 FROM tb_auth_organization_post 
			 WHERE fid = a.id) AS is_leaf,
			created_at, updated_at
		FROM tb_auth_organization_post a 
		ORDER BY fid ASC, id ASC
	`

	if err := a.Raw(sql).Scan(&allData).Error; err != nil {
		variable.ZapLog.Error("查询所有部门数据失败", zap.Error(err))
		return nil, err
	}

	// 构建树状结构
	treeData := a.buildTree(allData, rootFid)

	variable.ZapLog.Info("构建部门树状结构完成",
		zap.Int("total_departments", len(allData)),
		zap.Int("root_nodes", len(treeData)),
		zap.Int("root_fid", rootFid),
	)

	return treeData, nil
}

// GetAllAsTreeWithStatus 查询指定状态的部门数据并以树状结构返回
// @Description 根据状态过滤并递归构建部门组织架构的树状结构
// @Param rootFid int 根节点的父ID
// @Param status int 部门状态(1:启用, 0:禁用, -1:全部)
// @Return []AuthOrganizationPostTree 树状结构数据
func (a *AuthOrganizationPostModel) GetAllAsTreeWithStatus(rootFid int, status int) ([]AuthOrganizationPostTree, error) {
	// 查询指定状态的部门数据
	var allData []AuthOrganizationPostTree
	var sql string

	if status == -1 {
		// 查询所有状态
		sql = `
			SELECT  
				id, fid, title, node_type, status, path_info, node_level, remark,
				(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
				 FROM tb_auth_organization_post 
				 WHERE fid = a.id) AS is_leaf,
				created_at, updated_at
			FROM tb_auth_organization_post a 
			ORDER BY fid ASC, id ASC
		`
		if err := a.Raw(sql).Scan(&allData).Error; err != nil {
			variable.ZapLog.Error("查询所有状态部门数据失败", zap.Error(err))
			return nil, err
		}
	} else {
		// 查询指定状态
		sql = `
			SELECT  
				id, fid, title, node_type, status, path_info, node_level, remark,
				(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
				 FROM tb_auth_organization_post 
				 WHERE fid = a.id AND status = ?) AS is_leaf,
				created_at, updated_at
			FROM tb_auth_organization_post a 
			WHERE status = ?
			ORDER BY fid ASC, id ASC
		`
		if err := a.Raw(sql, status, status).Scan(&allData).Error; err != nil {
			variable.ZapLog.Error("查询指定状态部门数据失败",
				zap.Error(err),
				zap.Int("status", status),
			)
			return nil, err
		}
	}

	// 构建树状结构
	treeData := a.buildTree(allData, rootFid)

	variable.ZapLog.Info("构建指定状态部门树状结构完成",
		zap.Int("total_departments", len(allData)),
		zap.Int("root_nodes", len(treeData)),
		zap.Int("root_fid", rootFid),
		zap.Int("status", status),
	)

	return treeData, nil
}

// buildTree 递归构建树状结构的核心方法
// @Description 将扁平的部门数据递归构建成树状结构
// @Param allData []AuthOrganizationPostTree 所有部门数据
// @Param parentFid int 当前层级的父ID
// @Return []AuthOrganizationPostTree 当前层级的树状数据
func (a *AuthOrganizationPostModel) buildTree(allData []AuthOrganizationPostTree, parentFid int) []AuthOrganizationPostTree {
	var result []AuthOrganizationPostTree

	// 遍历所有数据，找到当前父节点的直接子节点
	for i := range allData {
		// 直接使用int类型的Fid进行比较
		if allData[i].Fid == parentFid {
			// 复制当前节点
			node := allData[i]

			// 递归查找当前节点的子节点
			node.Children = a.buildTree(allData, node.Id)

			// 更新is_leaf状态
			node.IsLeaf = len(node.Children) == 0

			result = append(result, node)
		}
	}

	return result
}

// GetTreePath 获取指定部门到根节点的路径
// @Description 根据部门ID获取从该部门到根节点的完整路径
// @Param departmentId int 部门ID
// @Return []AuthOrganizationPostTree 路径上的所有部门信息
func (a *AuthOrganizationPostModel) GetTreePath(departmentId int) ([]AuthOrganizationPostTree, error) {
	var path []AuthOrganizationPostTree
	var currentDept AuthOrganizationPostTree

	// 查询当前部门信息
	sql := `
		SELECT  
			id, fid, title, node_type, status, path_info, node_level, remark,
			(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
			 FROM tb_auth_organization_post 
			 WHERE fid = a.id) AS is_leaf
		FROM tb_auth_organization_post a 
		WHERE id = ?
	`

	if err := a.Raw(sql, departmentId).Scan(&currentDept).Error; err != nil {
		variable.ZapLog.Error("查询部门信息失败",
			zap.Error(err),
			zap.Int("department_id", departmentId),
		)
		return nil, err
	}

	// 如果部门不存在
	if currentDept.Id == 0 {
		return path, nil
	}

	// 将当前部门添加到路径
	path = append([]AuthOrganizationPostTree{currentDept}, path...)

	// 递归查找父部门
	if currentDept.Fid > 0 {
		if parentPath, err := a.GetTreePath(currentDept.Fid); err == nil {
			path = append(parentPath, path...)
		}
	}

	variable.ZapLog.Info("获取部门路径完成",
		zap.Int("department_id", departmentId),
		zap.Int("path_length", len(path)),
	)

	return path, nil
}

func (a *AuthOrganizationPostModel) GetAllDataByStatus(status int) ([]AuthOrganizationPostTree, error) {
	var result []AuthOrganizationPostTree
	err := a.Model(a).Where("status = ?", 1).Where("id <> ?", 1).Find(&result).Error
	return result, err
}

// GetByNodeType 根据节点类型查询数据
// @Description 根据节点类型查询数据：1=部门，2=角色/岗位
// @Param nodeType int 节点类型：1=部门，2=角色/岗位
// @Param status int 状态过滤，-1表示不过滤
// @Return []AuthOrganizationPostTree 树状结构数据
func (a *AuthOrganizationPostModel) GetByNodeType(nodeType int, status int) ([]AuthOrganizationPostTree, error) {
	var result []AuthOrganizationPostTree

	sql := `
		SELECT  
			id, fid, title, node_type, status, path_info, node_level, remark,
			(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
			 FROM tb_auth_organization_post 
			 WHERE fid = a.id) AS is_leaf
		FROM tb_auth_organization_post a 
		WHERE node_type = ?
	`

	var args []interface{}
	args = append(args, nodeType)

	if status != -1 {
		sql += " AND status = ?"
		args = append(args, status)
	}

	sql += " ORDER BY fid ASC, id ASC"

	if err := a.Raw(sql, args...).Scan(&result).Error; err != nil {
		variable.ZapLog.Error("根据节点类型查询数据失败",
			zap.Error(err),
			zap.Int("node_type", nodeType),
			zap.Int("status", status),
		)
		return nil, err
	}

	return result, nil
}

// GetRolesOnly 仅获取角色/岗位数据
// @Description 仅查询节点类型为角色/岗位的数据
// @Param status int 状态过滤，-1表示不过滤
// @Return []AuthOrganizationPostTree 角色/岗位数据
func (a *AuthOrganizationPostModel) GetRolesOnly(status int) ([]AuthOrganizationPostTree, error) {
	return a.GetByNodeType(2, status)
}

// GetPostsOnly 仅获取岗位数据（与GetRolesOnly相同，因为现在角色和岗位都是类型2）
// @Description 仅查询节点类型为岗位的数据
// @Param status int 状态过滤，-1表示不过滤
// @Return []AuthOrganizationPostTree 岗位数据
func (a *AuthOrganizationPostModel) GetPostsOnly(status int) ([]AuthOrganizationPostTree, error) {
	return a.GetByNodeType(2, status)
}

// GetDepartmentsOnly 仅获取部门数据
// @Description 仅查询节点类型为部门的数据
// @Param status int 状态过滤，-1表示不过滤
// @Return []AuthOrganizationPostTree 部门数据
func (a *AuthOrganizationPostModel) GetDepartmentsOnly(status int) ([]AuthOrganizationPostTree, error) {
	return a.GetByNodeType(1, status)
}

// GetDepartmentsAsTree 获取所有部门数据并以树状结构返回
// @Description 查询所有 node_type=1 且 status=1 的部门数据，并构建成树状结构
// @Param rootFid int 根节点的父ID，通常为0表示从顶级开始
// @Return []AuthOrganizationPostTree 部门树状结构数据
func (a *AuthOrganizationPostModel) GetDepartmentsAsTree(rootFid int) ([]AuthOrganizationPostTree, error) {
	// 严格查询只有部门类型的数据（node_type=1, status=1）
	var allDepartments []AuthOrganizationPostTree
	sql := `
		SELECT  
			id, fid, title, node_type, status, path_info, node_level, remark,
			(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE 0 END 
			 FROM tb_auth_organization_post 
			 WHERE fid = a.id AND node_type = 1) AS is_leaf,
			created_at, updated_at
		FROM tb_auth_organization_post a 
		WHERE a.node_type = 1 
		ORDER BY a.fid ASC, a.id ASC
	`

	if err := a.Raw(sql).Scan(&allDepartments).Error; err != nil {
		variable.ZapLog.Error("查询部门数据失败", zap.Error(err))
		return nil, err
	}

	variable.ZapLog.Info("查询到的部门数据",
		zap.Int("total_departments", len(allDepartments)),
		zap.Int("root_fid", rootFid))

	// 二次过滤：确保只包含部门数据
	var pureData []AuthOrganizationPostTree
	for _, dept := range allDepartments {
		if dept.NodeType == 1 { // 只保留部门
			pureData = append(pureData, dept)
		}
	}

	variable.ZapLog.Info("过滤后的部门数据",
		zap.Int("filtered_departments", len(pureData)))

	// 使用专门的部门树构建方法
	treeData := a.buildDepartmentTreeOnly(pureData, rootFid)

	variable.ZapLog.Info("构建部门树状结构完成",
		zap.Int("total_input", len(pureData)),
		zap.Int("root_nodes", len(treeData)),
		zap.Int("root_fid", rootFid))

	return treeData, nil
}

// buildDepartmentTreeOnly 专门用于部门树构建的方法，严格过滤角色数据
// @Description 严格只处理node_type=1的部门节点，完全忽略所有角色/岗位节点
// @Param departments []AuthOrganizationPostTree 所有部门数据（已预过滤）
// @Param parentFid int 当前层级的父ID
// @Return []AuthOrganizationPostTree 当前层级的纯部门树状数据
func (a *AuthOrganizationPostModel) buildDepartmentTreeOnly(departments []AuthOrganizationPostTree, parentFid int) []AuthOrganizationPostTree {
	var result []AuthOrganizationPostTree

	// 遍历所有部门数据
	for _, dept := range departments {
		// 三重检查：确保只处理部门
		if dept.NodeType != 1 {
			continue // 跳过非部门数据
		}

		// 直接使用int类型的Fid进行比较
		if dept.Fid == parentFid {
			// 复制部门节点
			node := dept

			// 递归查找子部门（只在部门中查找）
			node.Children = a.buildDepartmentTreeOnly(departments, node.Id)

			// 更新叶子节点状态
			node.IsLeaf = len(node.Children) == 0

			// 最后一次检查：确保节点是部门类型
			if node.NodeType == 1 {
				result = append(result, node)
			}
		}
	}

	return result
}

// GetAllRolesByFid 根据fid查询所有启用的角色/岗位数据，不分页
func (a *AuthOrganizationPostModel) GetAllRolesByFid(fid int) (data []AuthOrganizationPostModel) {
	a.Model(a).Select("id", "fid", "title", "node_type", "status", "path_info", "remark", "created_at", "updated_at").
		Where("node_type = ? AND fid = ? AND status = ?", 2, fid, 1). // 2表示角色/岗位，status=1表示启用
		Find(&data)
	return
}

// ==================== 角色专用方法 ====================

// InsertRoleData 插入角色数据（node_type=2）
func (a *AuthOrganizationPostModel) InsertRoleData(c *gin.Context) bool {
	var tmp AuthOrganizationPostModel
	if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
		// 强制设置为角色类型
		tmp.NodeType = 2

		var counts int64
		if res := a.Model(a).Where("fid=? and title=? and node_type=?", tmp.Fid, tmp.Title, 2).Count(&counts); res.Error == nil && counts > 0 {
			return false
		} else {
			if res := a.Create(&tmp); res.Error == nil {
				// 插入新数据时，如果提供了NodeLevel值则使用，否则自动计算
				var nodeLevel *int
				if tmp.NodeLevel > 0 {
					nodeLevel = &tmp.NodeLevel
				}
				_ = a.updatePathInfoNodeLevel(int(tmp.Id), nodeLevel)
				return true
			} else {
				variable.ZapLog.Error("角色数据新增出错：", zap.Error(res.Error))
			}
		}
	} else {
		variable.ZapLog.Error("角色数据从验证器绑定到model出错：", zap.Error(err))
	}
	return false
}

// UpdateRoleData 更新角色数据（node_type=2）
func (a *AuthOrganizationPostModel) UpdateRoleData(c *gin.Context) bool {
	var tmp AuthOrganizationPostModel

	if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
		// 强制设置为角色类型
		tmp.NodeType = 2

		// 检查是否为角色记录
		var existing AuthOrganizationPostModel
		if err := a.Model(a).Where("id = ? AND node_type = ?", tmp.Id, 2).First(&existing).Error; err != nil {
			variable.ZapLog.Error("角色记录不存在或不是角色类型：", zap.Error(err))
			return false
		}

		// Omit 表示忽略指定字段(CreatedAt)，其他字段全量更新
		if res := a.Omit("CreatedAt").Save(&tmp); res.Error == nil {
			// 如果提供了NodeLevel值，则传递该值，否则传递nil让系统自动计算
			var nodeLevel *int
			if tmp.NodeLevel > 0 {
				nodeLevel = &tmp.NodeLevel
			}
			_ = a.updatePathInfoNodeLevel(int(tmp.Id), nodeLevel)
			return true
		} else {
			variable.ZapLog.Error("角色数据更新失败：", zap.Error(res.Error))
		}
	} else {
		variable.ZapLog.Error("角色数据从验证器绑定到model出错：", zap.Error(err))
	}
	return false
}

// GetRoleById 根据ID查询单个角色数据
func (a *AuthOrganizationPostModel) GetRoleById(id int) (*AuthOrganizationPostModel, error) {
	var data AuthOrganizationPostModel
	err := a.Model(a).Where("id = ? AND node_type = ?", id, 2).First(&data).Error
	if err != nil {
		return nil, err
	}
	return &data, nil
}

func (a *AuthOrganizationPostModel) GetAllOrgPostIdAndTitleByIds(ids []int) (data []*OrgPostIdAndTitle) {
	a.Model(a).Select("id,title").Where("node_type = ? and id in (?)", 2, ids).Find(&data)
	return
}

// GetChildAllOrgPostIdById 获取指定ID的直接子节点ID（仅角色/岗位类型）
func (a *AuthOrganizationPostModel) GetChildAllOrgPostIdById(id int) (data []*OrgPostId) {
	a.Model(a).Select("id").Where("node_type = ? and fid = ?", 2, id).Find(&data)
	return
}

// GetAllChildIdsById 递归获取指定ID的所有层级子节点ID（支持所有类型节点）
// @Description 递归查询指定ID下的所有层级子节点ID，不限于直接子节点
// @Param id int 父节点ID
// @Param nodeType int 节点类型过滤（-1表示不过滤类型）
// @Return []int 所有子节点ID的切片
func (a *AuthOrganizationPostModel) GetAllChildIdsById(id int, nodeType int) ([]int, error) {
	var allChildIDs []int
	var currentLevelIDs []int

	// 将当前id加入结果列表
	allChildIDs = append(allChildIDs, int(id))

	// 初始层：查询直接子节点（fid = parentID）
	if err := a.Model(a).
		Where("fid = ?", id).
		Where("node_type = ?", nodeType).
		Pluck("id", &currentLevelIDs).Error; err != nil {
		return nil, err
	}
	allChildIDs = append(allChildIDs, currentLevelIDs...)

	// 循环查询后续层（直到无新子节点）
	for len(currentLevelIDs) > 0 {
		var nextLevelIDs []int
		// 链式查询：当前层的子节点（fid 在 currentLevelIDs 中）
		err := a.Model(a).
			Where("fid IN ?", currentLevelIDs).
			Where("node_type = ?", nodeType).
			Pluck("id", &nextLevelIDs).Error
		if err != nil {
			return nil, err
		}
		// 合并结果
		allChildIDs = append(allChildIDs, nextLevelIDs...)
		// 更新当前层为新查询的子节点 ID（用于下一轮循环）
		currentLevelIDs = nextLevelIDs
	}

	return allChildIDs, nil
}

// GetAllChildRoleIdNameById 递归获取指定ID下所有子节点的ID和Title
// @param id 父节点ID
// @param nodeType 节点类型
// @Return []OrgPostIdAndTitle 所有子节点ID和Title的切片
func (a *AuthOrganizationPostModel) GetAllChildRoleIdNameById(id int, nodeType int) ([]OrgPostIdAndTitle, error) {
	var allChildIDAndTitles []OrgPostIdAndTitle
	var currentLevelIDs []int

	if id == 0 {
		err := a.Model(a).Select("id", "title").Where("node_type = ?", nodeType).Find(&allChildIDAndTitles).Error
		return allChildIDAndTitles, err
	}

	// 初始层：查询直接子节点（fid = parentID）
	var directChildren, nextLevelIDAndTitles []OrgPostIdAndTitle
	if err := a.Model(a).
		Select("id", "title").
		Where("fid = ?", id).
		Where("node_type = ?", 1).
		Find(&directChildren).Error; err != nil {
		return nil, err
	}

	if err := a.Model(a).
		Select("id", "title").
		Where("fid = ?", id).
		Where("node_type = ?", 2).
		Find(&nextLevelIDAndTitles).Error; err != nil {
		return nil, err
	}

	// 添加直接子节点到结果列表
	allChildIDAndTitles = append(allChildIDAndTitles, nextLevelIDAndTitles...)

	// 收集直接子节点的ID，用于递归查询下一层
	for _, child := range directChildren {
		currentLevelIDs = append(currentLevelIDs, child.Id)
	}

	// 循环查询后续层（直到无新子节点）
	for len(currentLevelIDs) > 0 {
		var nextLevelIDAndTitles []OrgPostIdAndTitle

		// 链式查询：当前层的子节点（fid 在 currentLevelIDs 中）
		err := a.Model(a).
			Select("id", "title").
			Where("fid IN ?", currentLevelIDs).
			Where("node_type = ?", nodeType).
			Find(&nextLevelIDAndTitles).Error
		if err != nil {
			return nil, err
		}

		// 合并结果
		allChildIDAndTitles = append(allChildIDAndTitles, nextLevelIDAndTitles...)

		// 清空当前层ID，准备收集下一层ID
		currentLevelIDs = currentLevelIDs[:0]

		// 收集下一层子节点的ID，用于下一轮循环
		for _, child := range nextLevelIDAndTitles {
			currentLevelIDs = append(currentLevelIDs, child.Id)
		}
	}

	return allChildIDAndTitles, nil
}
